import { CacheManager } from './cache'

// API缓存配置
export interface ApiCacheConfig {
    ttl: number
    maxSize: number
    staleWhileRevalidate: boolean
    retryOnError: boolean
}

// 默认缓存配置
const DEFAULT_CACHE_CONFIG: ApiCacheConfig = {
    ttl: 5 * 60 * 1000, // 5分钟
    maxSize: 100,
    staleWhileRevalidate: true,
    retryOnError: true
}

// 不同类型数据的缓存策略
export const CACHE_STRATEGIES = {
    // 数据集信息 - 长期缓存
    datasets: {
        ttl: 30 * 60 * 1000, // 30分钟
        maxSize: 50,
        staleWhileRevalidate: true,
        retryOnError: true
    },
    // 影像数据 - 中期缓存
    images: {
        ttl: 15 * 60 * 1000, // 15分钟
        maxSize: 20,
        staleWhileRevalidate: true,
        retryOnError: true
    },
    // 任务结果 - 短期缓存
    tasks: {
        ttl: 2 * 60 * 1000, // 2分钟
        maxSize: 30,
        staleWhileRevalidate: false,
        retryOnError: true
    },
    // 元数据 - 长期缓存
    metadata: {
        ttl: 60 * 60 * 1000, // 1小时
        maxSize: 100,
        staleWhileRevalidate: true,
        retryOnError: true
    }
} as const

// API缓存管理器
export class ApiCacheManager {
    private caches: Map<string, CacheManager> = new Map()
    private requestQueue: Map<string, Promise<any>> = new Map()

    constructor() {
        // 为不同类型的数据创建专门的缓存
        Object.entries(CACHE_STRATEGIES).forEach(([type, config]) => {
            this.caches.set(type, new CacheManager(config.maxSize, config.ttl))
        })
    }

    // 获取指定类型的缓存管理器
    private getCache(type: keyof typeof CACHE_STRATEGIES): CacheManager {
        const cache = this.caches.get(type)
        if (!cache) {
            throw new Error(`Cache type ${type} not found`)
        }
        return cache
    }

    // 缓存API响应
    async cacheApiCall<T>(
        type: keyof typeof CACHE_STRATEGIES,
        key: string,
        apiCall: () => Promise<T>,
        options?: Partial<ApiCacheConfig>
    ): Promise<T> {
        const cache = this.getCache(type)
        const strategy = CACHE_STRATEGIES[type]
        const config = { ...strategy, ...options }

        // 检查缓存
        const cached = cache.get(key)
        if (cached) {
            // 如果启用了 stale-while-revalidate，在后台更新数据
            if (config.staleWhileRevalidate) {
                this.backgroundRefresh(type, key, apiCall)
            }
            return cached
        }

        // 防止重复请求
        const existingRequest = this.requestQueue.get(key)
        if (existingRequest) {
            return existingRequest
        }

        // 执行API调用
        const request = this.executeApiCall(apiCall, config.retryOnError)
        this.requestQueue.set(key, request)

        try {
            const result = await request
            cache.set(key, result, config.ttl)
            return result
        } finally {
            this.requestQueue.delete(key)
        }
    }

    // 后台刷新数据
    private async backgroundRefresh<T>(
        type: keyof typeof CACHE_STRATEGIES,
        key: string,
        apiCall: () => Promise<T>
    ): Promise<void> {
        try {
            const result = await apiCall()
            const cache = this.getCache(type)
            cache.set(key, result)
        } catch (error) {
            console.warn(`Background refresh failed for ${key}:`, error)
        }
    }

    // 执行API调用（带重试机制）
    private async executeApiCall<T>(
        apiCall: () => Promise<T>,
        retryOnError: boolean,
        maxRetries = 3
    ): Promise<T> {
        let lastError: Error

        for (let attempt = 0; attempt <= maxRetries; attempt++) {
            try {
                return await apiCall()
            } catch (error) {
                lastError = error as Error

                if (!retryOnError || attempt === maxRetries) {
                    throw error
                }

                // 指数退避
                const delay = Math.min(1000 * Math.pow(2, attempt), 5000)
                await new Promise(resolve => setTimeout(resolve, delay))
            }
        }

        throw lastError!
    }

    // 预取数据
    async prefetch<T>(
        type: keyof typeof CACHE_STRATEGIES,
        key: string,
        apiCall: () => Promise<T>
    ): Promise<void> {
        const cache = this.getCache(type)

        // 如果已经缓存，跳过
        if (cache.has(key)) {
            return
        }

        try {
            const result = await apiCall()
            cache.set(key, result)
        } catch (error) {
            console.warn(`Prefetch failed for ${key}:`, error)
        }
    }

    // 批量预取
    async batchPrefetch<T>(
        type: keyof typeof CACHE_STRATEGIES,
        requests: Array<{ key: string; apiCall: () => Promise<T> }>
    ): Promise<void> {
        const promises = requests.map(({ key, apiCall }) =>
            this.prefetch(type, key, apiCall)
        )
        await Promise.allSettled(promises)
    }

    // 使缓存失效
    invalidate(type: keyof typeof CACHE_STRATEGIES, key?: string): void {
        const cache = this.getCache(type)
        if (key) {
            cache.delete(key)
        } else {
            cache.clear()
        }
    }

    // 获取缓存统计
    getStats() {
        const stats: Record<string, any> = {}
        for (const [type, cache] of this.caches) {
            stats[type] = cache.getStats()
        }
        return stats
    }

    // 清理所有缓存
    clearAll(): void {
        for (const cache of this.caches.values()) {
            cache.clear()
        }
        this.requestQueue.clear()
    }

    // 销毁缓存管理器
    destroy(): void {
        for (const cache of this.caches.values()) {
            cache.destroy()
        }
        this.caches.clear()
        this.requestQueue.clear()
    }
}

// 全局API缓存实例
export const apiCache = new ApiCacheManager()

// API缓存装饰器
export function withApiCache(
    type: keyof typeof CACHE_STRATEGIES,
    keyGenerator?: (...args: any[]) => string
) {
    return function (target: any, propertyName: string, descriptor: PropertyDescriptor) {
        const method = descriptor.value

        descriptor.value = async function (...args: any[]) {
            const key = keyGenerator ? keyGenerator(...args) : `${propertyName}_${JSON.stringify(args)}`

            return apiCache.cacheApiCall(
                type,
                key,
                () => method.apply(this, args)
            )
        }
    }
}

// React Hook for API caching
export function useApiCache() {
    const cacheApiCall = <T>(
        type: keyof typeof CACHE_STRATEGIES,
        key: string,
        apiCall: () => Promise<T>,
        options?: Partial<ApiCacheConfig>
    ) => {
        return apiCache.cacheApiCall(type, key, apiCall, options)
    }

    const prefetch = <T>(
        type: keyof typeof CACHE_STRATEGIES,
        key: string,
        apiCall: () => Promise<T>
    ) => {
        return apiCache.prefetch(type, key, apiCall)
    }

    const invalidate = (type: keyof typeof CACHE_STRATEGIES, key?: string) => {
        apiCache.invalidate(type, key)
    }

    const getStats = () => {
        return apiCache.getStats()
    }

    return {
        cacheApiCall,
        prefetch,
        invalidate,
        getStats
    }
}

// 智能缓存键生成器
export class CacheKeyGenerator {
    static forDataset(id: string): string {
        return `dataset_${id}`
    }

    static forImage(imageId: string, params?: Record<string, any>): string {
        const paramStr = params ? `_${JSON.stringify(params)}` : ''
        return `image_${imageId}${paramStr}`
    }

    static forTask(datasetId: string, taskId: string): string {
        return `task_${datasetId}_${taskId}`
    }

    static forTaskResult(taskId: string, timestamp?: number): string {
        const ts = timestamp ? `_${timestamp}` : ''
        return `task_result_${taskId}${ts}`
    }

    static forMetadata(type: string, id: string): string {
        return `metadata_${type}_${id}`
    }
}